﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.IO;
using System.Collections.ObjectModel;
using System.Diagnostics;

namespace WinSilver
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        static Dictionary<string, string> dic = new Dictionary<string, string>();

        List<string> resultList = new List<string>();
        
        ObservableCollection<string> resultsCollection = new ObservableCollection<string>();

        public MainWindow()
        {
            InitializeComponent();
            expandChrome(false);
            DataContext = resultsCollection;
            refreshCache();
        }

        private void Window_Activated(object sender, EventArgs e)
        {
            TextSearch.Focus();
        }

        private void TextSearch_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Return:
                    this.Close(); // execute string!
                    executeAppByKey(AppList.SelectedItem.ToString());
                    break;

                case Key.Escape:
                    this.Close();
                    break;
                
                case Key.Down:
                    AppList.SelectedIndex += AppList.SelectedIndex < AppList.Items.Count ? 1 : 0;
                    AppList.ScrollIntoView(AppList.SelectedItem);
                    break;

                case Key.Up:
                    AppList.SelectedIndex += AppList.SelectedIndex > 0 ? -1 : 0;
                    AppList.ScrollIntoView(AppList.SelectedItem);
                    break;

                default:
                    string typedText = ((TextBox)sender).Text.ToString().Trim();
                    processString(typedText);
                    break;
            }
        }

        private void processString(string str)
        {
            str = str.Trim().ToLower();

            resultsCollection.Clear();

            if (str.Length > 1)
            {
                resultList.Clear();

                foreach (KeyValuePair<string, string> pair in dic)
                {
                    // add to the list what is found and also leave out the crap
                    if (pair.Key.Contains(str) && 
                        !pair.Key.Contains("uninstall") && 
                        !pair.Key.Contains("help") && 
                        !pair.Key.Contains("readme") && 
                        !pair.Key.Contains("read me") && 
                        !pair.Key.Contains("what's new")
                       )
                    {
                        resultList.Add(pair.Key);
                    }
                }

                resultList.Sort();

                // send to the observable collection to show in list
                resultList.ForEach(x => resultsCollection.Add(x));

                AppList.SelectedIndex = 0;
            }

            if (AppList.Items.Count > 0)
            {
                expandChrome(true);
            }
            else
            {
                expandChrome(false);
            }
        }

        private void expandChrome(bool expand = true)
        {
            if (expand == true)
            {
                Chrome.Height = 400;
            }
            else
            {
                Chrome.Height = 60;
            }
        }

        private void executeAppByKey(string keyString)
        {
            foreach (KeyValuePair<string, string> pair in dic)
            {
                if (pair.Key == keyString)
                {
                    Process.Start(pair.Value);
                }
            }
        }

        private void refreshCache()
        {
            // see wikipedia for locations http://en.wikipedia.org/wiki/Start_menu
            // see answers http://stackoverflow.com/questions/3236754/c-process-start-a-clickonce-application-what-url
            // recursive find file http://dotnetperls.com/recursively-find-files

            // get user folders where there are links
            List<string> lst1 = FileHelper.GetFilesRecursive(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu));
            List<string> lst2 = FileHelper.GetFilesRecursive(Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu));

            // merge the two lists
            lst1.AddRange(lst2);

            // remove duplicates (1)
            List<string> noDupes = lst1.Distinct().ToList();

            string filename;

            foreach (string fullPath in noDupes)
            {
                filename = Path.GetFileNameWithoutExtension(fullPath.Trim().ToLower());

                // check for duplicates (2) between startup menus...
                if (!dic.ContainsKey(filename))
                {
                    dic.Add(filename, fullPath);
                }
            }

        }

        private void Window_Deactivated(object sender, EventArgs e)
        {
            //this.Close();
        }


        /// <summary>
        /// Compute Levenshtein distance - NOT USED AT THE MOMENT
        /// </summary>
        /// <param name="s">String 1</param>
        /// <param name="t">String 2</param>
        /// <returns>Distance between the two strings.
        /// The larger the number, the bigger the difference.
        /// </returns>
        public static int LeventshteinDistance(string s, string t)
        {
            int n = s.Length; //length of s
            int m = t.Length; //length of t
            int[,] d = new int[n + 1, m + 1]; // matrix
            int cost; // cost

            if (n == 0) return m;
            if (m == 0) return n;

            for (int i = 0; i <= n; d[i, 0] = i++) ;
            for (int j = 0; j <= m; d[0, j] = j++) ;

            for (int i = 1; i <= n; i++)
            {
                for (int j = 1; j <= m; j++)
                {
                    cost = (t.Substring(j - 1, 1) == s.Substring(i - 1, 1) ? 0 : 1);
                    d[i, j] = System.Math.Min(System.Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
                }
            }

            return d[n, m];
        }

        private void TextSearch_KeyUp(object sender, KeyEventArgs e)
        {

        }

    }
}
